﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServEvo.Layout.Interfaces;
using ServEvo.Layout.Enum;
using System.Threading.Tasks;
using System.ServiceProcess;
using System.Diagnostics;

namespace ServEvo.ServControl
{
    class AdminManager : MainManager, IServeur, IAdminService
    {
        protected List<Service> _listServices;
        protected Dictionary<Service, ServiceController> _listServiceController;
        protected Dictionary<Service, Process> _listProcess;
        protected Dictionary<Service, ProcessStartInfo> _listProcessStartInfo;
        protected Dictionary<Service, int> _listProcessId;
        protected bool _isServiceInstalled;

        public void Dispose()
        {
            stopServeur();
            foreach (KeyValuePair<Service, Process> o in _listProcess)
            {
                o.Value.Dispose();
            }
            foreach (KeyValuePair<Service, ServiceController> o in _listServiceController)
            {
                o.Value.Dispose();
            }
        }
        List<Service> getListServices()
        {
            return _listServices;
        }
        List<Service> IService.getListServices()
        {
            return _listServices;
        }

        List<Service> getListServeurs()
        {
            return _listServices;
        }
        List<Service> IServeur.getListServeurs()
        {
            return _listServices;
        }

        protected void initList()
        {
            _listServiceController = new Dictionary<Service, ServiceController>();
            _listProcess = new Dictionary<Service, Process>();
            _listProcessStartInfo = new Dictionary<Service, ProcessStartInfo>();
            _listProcessId = new Dictionary<Service, int>();

            foreach (Service service in _listServices)
            {
                _listProcess.Add(service, null);
                _listProcessStartInfo.Add(service, null);
                _listProcessId.Add(service, 0);
            }
            foreach (Service service in _listServices)
            {
                _listServiceController.Add(service, null);
            }
        }

        #region Services
            public bool isServiceStarted()
            {
                bool bStatut = true;
                foreach (Service service in _listServices)
                {
                    bStatut &= isServiceStarted(service);
                }
                return bStatut;
            }
            public bool isServiceStarted(Service service)
            {
                bool bRetour = false;
                if (_listServices.Contains(service))
                {
                    _listServiceController[service].Refresh();
                    if (_listServiceController[service].Status == ServiceControllerStatus.Running) bRetour = true;
                }
                return bRetour;
            }

            public void startService()
            {
                foreach (Service service in _listServices)
                {
                    startService(service);
                }
            }
            public void startService(Service service)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(service))
                    {
                        _listServiceController[service].Refresh();
                        if (_listServiceController[service].Status == ServiceControllerStatus.Stopped)
                        {
                            _listServiceController[service].Start();
                            //scHTTP.WaitForStatus(ServiceControllerStatus.Running);
                        }
                        else
                        {
                            if (_listServiceController[service].Status == ServiceControllerStatus.StopPending)
                            {
                                _listServiceController[service].WaitForStatus(ServiceControllerStatus.Stopped);
                                _listServiceController[service].Start();
                            }
                        }
                    }
                }
            }

            public void restartService()
            {
                foreach (Service service in _listServices)
                {
                    restartService(service);
                }
            }
            public void restartService(Service service)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(service))
                    {
                        _listServiceController[service].Refresh();
                        stopService(service);
                        _listServiceController[service].WaitForStatus(ServiceControllerStatus.Stopped);
                        startService(service);
                    }
                }
            }

            public void stopService()
            {
                foreach (Service service in _listServices)
                {
                    stopService(service);
                }
            }
            public void stopService(Service service)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(service))
                    {
                        _listServiceController[service].Refresh();
                        if (_listServiceController[service].Status == ServiceControllerStatus.Running
                            || _listServiceController[service].Status == ServiceControllerStatus.Paused)
                        {
                            _listServiceController[service].Stop();
                        }
                        else
                        {
                            if (_listServiceController[service].Status == ServiceControllerStatus.ContinuePending)
                            {
                                _listServiceController[service].WaitForStatus(ServiceControllerStatus.Running);
                                _listServiceController[service].Stop();
                            }
                        }
                    }
                }
            }

            public void installService()
            {
                foreach (Service service in _listServices)
                {
                    installService(service);
                }
            }
            public void installService(Service service)
            {
                throw new NotImplementedException();
            }

            public void uninstallService()
            {
                foreach (Service service in _listServices)
                {
                    uninstallService(service);
                }
            }
            public void uninstallService(Service service)
            {
                throw new NotImplementedException();
            }
        #endregion

        #region Serveurs
            public bool isServeurStarted()
            {
                bool bStatut = true;
                foreach (Service serveur in _listServices)
                {
                    bStatut &= isServeurStarted(serveur);
                }
                return bStatut;
            }
            public bool isServeurStarted(Service serveur)
            {
                bool bStatut = false;
                if (_listServices.Contains(serveur))
                {
                    if (_listProcessId.ContainsKey(serveur) && _listProcessId[serveur] != 0)
                    {
                        try
                        {
                            _listProcess[serveur] = Process.GetProcessById(_listProcessId[serveur]);
                            bStatut = true;
                        } 
                        catch(ArgumentException)
                        {
                            _listProcess[serveur] = null;
                            _listProcessId[serveur] = 0;
                        }
                    }
                }
                return bStatut;
            }

            public void startServeur()
            {
                foreach (Service serveur in _listServices)
                {
                    startServeur(serveur);
                }
            }
            public void startServeur(Service serveur)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(serveur))
                    {
                        try
                        {
                            _listProcess[serveur] = Process.Start(_listProcessStartInfo[serveur]);
                            _listProcessId[serveur] = _listProcess[serveur].Id;
                        }
                        catch (Exception)
                        {
                            _listProcessId[serveur] = 0;
                        }
                    }
                }
            }

            public void restartServeur()
            {
                foreach (Service serveur in _listServices)
                {
                    restartServeur(serveur);
                }
            }
            public void restartServeur(Service serveur)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(serveur))
                    {
                        startServeur(serveur);
                        stopServeur(serveur);
                    }
                }
            }

            public void stopServeur()
            {
                foreach (Service serveur in _listServices)
                {
                    stopServeur(serveur);
                }
            }
            public void stopServeur(Service serveur)
            {
                lock (oLock)
                {
                    if (_listServices.Contains(serveur))
                    {
                        try
                        {
                            if (_listProcessId.ContainsKey(serveur) && _listProcessId[serveur] > 0)
                            {
                                _listProcess[serveur] = Process.GetProcessById(_listProcessId[serveur]);
                                Process[] pListHTTP = Process.GetProcessesByName(_listProcess[serveur].ProcessName);
                                foreach (Process pHttp in pListHTTP)
                                {
                                    pHttp.Kill();
                                }
                                _listProcessId[serveur] = 0;
                            }
                        }
                        catch (Exception) { _listProcessId[serveur] = 0; }
                    }
                }
            }
        #endregion
    }
}
